package com.gsy.controller.student;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gsy.aop.annotation.ParameterValid;
import com.gsy.aop.annotation.TokenValid;
import com.gsy.constant.GlobalConstant;
import com.gsy.entity.HealthEntity;
import com.gsy.entity.ModelEntity;
import com.gsy.entity.UserEntity;
import com.gsy.exception.TokenErrorException;
import com.gsy.request.GetUsersByTypeAndCharRequest;
import com.gsy.request.UpUserdataRequest;
import com.gsy.service.HealthService;
import com.gsy.utils.*;
import com.gsy.vo.GetUserDataByIdVO;
import com.gsy.enumerate.SystemStatusEnum;
import com.gsy.request.LoginRequest;
import com.gsy.request.UpPwdRequest;
import com.gsy.response.BaseResponse;
import com.gsy.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author gsy
 * @since 2022-03-03
 */
@RestController
@RequestMapping(consumes = "application/json", produces = "application/json")
@Api(value = "controller", tags = {"tb_user 操作接口"})
public class UserController {

    private final static Logger LOGGER = LoggerFactory.getLogger(UserController.class);

    @Resource
    private UserService userService;

    @Resource
    private HealthService healthService;

    /**
     * 个人密码修改
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "个人密码修改", notes = "个人密码修改")
    @PostMapping("users/upPwd")
    @ParameterValid(apiName = "个人密码修改", formatObj = UpPwdRequest.class)
    @TokenValid
    public BaseResponse upPwdRequest(@RequestBody UpPwdRequest request) {

        UserEntity userEntity = new UserEntity();
        userEntity.setId(request.getUid());
        userEntity.setPassword(MD5Util.encode(request.getOldpassword()));

        UserEntity entity = userService.getOne(Wrappers.lambdaQuery(userEntity));
        if (entity == null) {
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "原始密码错误！");
        }
        userEntity.setPassword(MD5Util.encode(request.getNewpassword()));

        boolean flag = userService.updateById(userEntity);
        if (flag) {
            return new BaseResponse(SystemStatusEnum.SUCCESS);
        } else {
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "修改失败！");
        }
    }

    /**
     * 用户头像修改
     *
     * @return
     */
    @ApiOperation(value = "用户头像修改", notes = "用户头像修改")
    @GetMapping("users/upicon/{uId}")
    @TokenValid
    public BaseResponse upicon(@PathVariable Integer uId, @RequestParam String url) {

        UserEntity userEntity = new UserEntity();
        userEntity.setId(uId);
        userEntity.setHead(url);

        boolean flag = userService.updateById(userEntity);
        if (flag) {
            return new BaseResponse(SystemStatusEnum.SUCCESS);
        } else {
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "修改失败！");
        }
    }

    /**
     * 用户头像上传
     *
     * @return
     */
    @PostMapping("upload")
    public BaseResponse upload(MultipartFile file) {

        String url = OSSUtil.upload(file, OSSUtil.FileDirType.AVATAR);

        BaseResponse success = new BaseResponse(SystemStatusEnum.SUCCESS);
        success.setData(url);
        return success;
    }

    /**
     * 用户修改
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "用户修改", notes = "用户修改")
    @PostMapping("users/upUserdata")
    @ParameterValid(apiName = "用户修改", formatObj = UpUserdataRequest.class)
    @TokenValid
    public BaseResponse upUserdata(@RequestBody UpUserdataRequest request) {

        UserEntity userEntity = userService.getById(request.getId());
        if (userEntity == null) {
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "用户不存在！");
        }

        String username = userEntity.getUsername();
        BeanUtils.copyProperties(request, userEntity);
        userEntity.setUsername(username);
        userEntity.setName(request.getUsername());
        boolean flag = userService.updateById(userEntity);
        if (flag) {
            return new BaseResponse(SystemStatusEnum.SUCCESS);
        } else {
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "修改失败！");
        }
    }


    /**
     * 删除tb_user信息
     *
     * @param uId
     * @return
     */
    @ApiOperation(value = "删除tb_user信息", notes = "根据请求参数信息删除tb_user信息")
    @GetMapping("users/delUserdata/{uId}")
    @TokenValid
    public BaseResponse deleteUser(@PathVariable Integer uId) {
        UserEntity entity = userService.getById(uId);

        if (entity == null) {
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "不存在该条信息！");
        }
        if (entity.getId() == 0) {
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "无法删除超级管理员！");
        }

        userService.removeById(uId);
        return new BaseResponse(SystemStatusEnum.SUCCESS);

    }

    /**
     * 登录
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "登录", notes = "登录")
    @PostMapping("users/login")
    @ParameterValid(apiName = "登录", formatObj = LoginRequest.class)
    public BaseResponse getUserList(@RequestBody LoginRequest request) {

        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(request, userEntity);
        userEntity.setPassword(MD5Util.encode(request.getPassword()));
        QueryWrapper<UserEntity> queryWrapper = new QueryWrapper<>(userEntity);
        List<UserEntity> entities = userService.list(queryWrapper);

        if (CollectionUtil.isNotEmpty(entities)) {
            BaseResponse success = new BaseResponse(SystemStatusEnum.SUCCESS);
            HashMap<String, Object> map = new HashMap<>();
            UserEntity entity = entities.get(0);
            map.put("id", entity.getId());
            map.put("username", entity.getUsername());
            map.put("password", entity.getPassword());
            String token = JwtUtils.sinToken(entity.getId(), entity.getUsername(), entity.getType());

            map.put("token", token);
            map.put("avatar", entity.getHead());
//
//            switch (userEntity.getType()){
//                case 0:
//                    RedisCacheUtils.putCache(GlobalConstant.SESSION_LOGIN_KEY + userEntity.getId(), token, 60 * 60 * 24);
//                    break;
//                case 1:
//                    RedisCacheUtils.putCache(GlobalConstant.SESSION_LOGIN_KEY + userEntity.getId(), token, 60 * 60 * 24);
//                    break;
//                default:
//                    RedisCacheUtils.putCache(GlobalConstant.SESSION_LOGIN_KEY + userEntity.getId(), token, 60 * 60 * 24);
//            }
            RedisCacheUtils.putCache(GlobalConstant.SESSION_LOGIN_KEY + entity.getId(), token, 60 * 60 * 24);

            success.setData(map);
            return success;
        } else {
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "账号或密码错误！");
        }
    }

    /**
     * 退出登录
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "退出登录", notes = "退出登录")
    @GetMapping("users/logout")
    public BaseResponse logout(HttpServletRequest request) {

        String accessToken = request.getHeader("Authorization") == null ? "" : request.getHeader("Authorization");
        if (StringUtils.isNotBlank(accessToken)) {

            LOGGER.info("accessToken is {}", accessToken);
            if (org.apache.commons.lang3.StringUtils.isNotBlank(accessToken)) {
                String[] split = accessToken.split("Bearer ");
                accessToken = split[1];
            }
            Map<String, Object> userInfo = JwtUtils.verity(accessToken);
            long userId = Long.parseLong(String.valueOf(userInfo.get("userId")));
            RedisCacheUtils.del(GlobalConstant.SESSION_LOGIN_KEY + userId);
        }
        return new BaseResponse(SystemStatusEnum.SUCCESS);
    }

    public static void main(String[] args) {
        UserEntity userEntity = new UserEntity();
        userEntity.setId(100);
        userEntity.setUsername("测试");
        userEntity.setType(1);
        String token = JwtUtils.sinToken(userEntity.getId(), userEntity.getUsername(), userEntity.getType());
        System.out.println(token);

        Map<String, Object> verity = JwtUtils.verity(token);
        System.out.println(verity);

    }

    /**
     * 个人信息获取
     *
     * @param id
     * @return
     */
    @ApiOperation(value = "个人信息获取", notes = "个人信息获取")
    @GetMapping("users/getUserDataById/{id}")
    @TokenValid
    public BaseResponse getUserDataById(@PathVariable Long id) {

        UserEntity userEntity = userService.getById(id);
        if (userEntity == null) {
            return new BaseResponse(SystemStatusEnum.SUCCESS.getCode(), "该用户不存在！");
        }
        userEntity.setUsername(userEntity.getName());
        GetUserDataByIdVO vo = new GetUserDataByIdVO();
        BeanUtil.copyProperties(userEntity, vo);
        BaseResponse success = new BaseResponse(SystemStatusEnum.SUCCESS);
        success.setData(vo);
        return success;
    }

    /**
     * 根据用户类型进行用户信息获取(分页获取总数量与数据)
     *
     * @return
     */
    @ApiOperation(value = "根据用户类型进行用户信息获取(分页获取总数量与数据)", notes = "根据用户类型进行用户信息获取(分页获取总数量与数据)")
    @GetMapping("users/getUsersByTypePage/{type}/{currPage}/{pageNum}")
    @TokenValid
    public BaseResponse getUsersByTypePage(@PathVariable Long type, @PathVariable Long pageNum, @PathVariable Long currPage) {

        Page<UserEntity> page = userService.page(new Page<>(currPage, pageNum),
                Wrappers.lambdaQuery(new UserEntity()).eq(UserEntity::getType, type)
        );
//        int hasHeSuan = healthService.count(Wrappers.lambdaQuery(new HealthEntity()).eq(HealthEntity::getHesuan, "是")
//                .groupBy(HealthEntity::getUId));

        List<UserEntity> entities = page.getRecords();
        entities.forEach(e -> {
            e.setUsername(e.getName());
        });

        if (CollectionUtil.isNotEmpty(entities)) {
            BaseResponse success = new BaseResponse(SystemStatusEnum.SUCCESS);
            success.setData(entities);
            success.setTotal(page.getTotal());
            return success;
        } else {
            return new BaseResponse(SystemStatusEnum.SUCCESS.getCode(), "获取数据为空！");
        }
    }

    /**
     * 所有用户信息获取
     *
     * @return
     */
    @ApiOperation(value = "所有用户信息获取", notes = "所有用户信息获取")
    @GetMapping("/users/getAllUsers/{currPage}/{pageNum}")
    @TokenValid
    public BaseResponse getAllUsers(@PathVariable Long pageNum, @PathVariable Long currPage) {

        Page<UserEntity> page = userService.page(new Page<>(currPage, pageNum));

        List<UserEntity> entities = page.getRecords();

        if (CollectionUtil.isNotEmpty(entities)) {
            BaseResponse success = new BaseResponse(SystemStatusEnum.SUCCESS);
            success.setData(entities);
            success.setTotal(page.getTotal());
            return success;
        } else {
            return new BaseResponse(SystemStatusEnum.SUCCESS.getCode(), "获取数据为空！");
        }
    }

    /**
     * 查询会话
     *
     * @return
     */
    @ApiOperation(value = "所有用户信息获取", notes = "所有用户信息获取")
    @GetMapping("/admin/getUserDataByToken/{token}")
    @TokenValid
    public BaseResponse getUserDataByToken(@PathVariable String token) {

        Map<String, Object> verity = JwtUtils.verity(token);
        Long userId = Long.valueOf(String.valueOf(verity.get("userId")));
        if (!RedisCacheUtils.hasKey(GlobalConstant.SESSION_LOGIN_KEY + userId)) {
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "登录已过期，请重新登录！");
        }
        RedisCacheUtils.putCache(GlobalConstant.SESSION_LOGIN_KEY + userId, userId, 60 * 60 * 24);
        UserEntity userEntity = userService.getById(userId);

        BaseResponse success = new BaseResponse(SystemStatusEnum.SUCCESS);
        success.setData(userEntity);
        return success;
    }

    /**
     * 批量导入用户
     *
     * @return
     */
    @ApiOperation(value = "批量导入用户", notes = "批量导入用户")
    @PostMapping("/users/saveByExcel")
    public BaseResponse saveByExcel(@RequestBody List<ModelEntity> request) {

        // 防止数据库中已经存在的用户重复添加
        List<String> usernameList = request.stream().map(ModelEntity::getUsername).collect(Collectors.toList());
        List<UserEntity> list = userService.list(Wrappers.lambdaQuery(new UserEntity())
                .in(UserEntity::getUsername, usernameList)
                .select(UserEntity::getUsername));
        if (CollectionUtils.isNotEmpty(list)) {
            StringBuilder stringBuilder = new StringBuilder();
            for (UserEntity userEntity : list) {
                stringBuilder.append(userEntity.getUsername()).append("，");
            }
            stringBuilder.deleteCharAt(stringBuilder.lastIndexOf("，"));
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "以下用户已存在：" + stringBuilder.toString());
        }
        // 防止数据库中已经存在的学号重复添加
        List<Long> studentNumberList = request.stream().map(ModelEntity::getStudentNumber).collect(Collectors.toList());
        List<UserEntity> userEntities = userService.list(Wrappers.lambdaQuery(new UserEntity())
                .in(UserEntity::getStudentNumber, studentNumberList)
                .select(UserEntity::getStudentNumber));
        if (CollectionUtils.isNotEmpty(userEntities)) {
            StringBuilder stringBuilder = new StringBuilder();
            for (UserEntity userEntity : userEntities) {
                stringBuilder.append(userEntity.getStudentNumber()).append("，");
            }
            stringBuilder.deleteCharAt(stringBuilder.lastIndexOf("，"));
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), "以下学号已存在：" + stringBuilder.toString());
        }
        // type类型校验
        List<ModelEntity> collect = request.stream().filter(e ->
                e.getType() != 2 &&
                        e.getType() != 3).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(collect)) {
            StringBuilder stringBuilder = new StringBuilder();
            for (ModelEntity userEntity : collect) {
                stringBuilder.append(userEntity.getUsername()).append("\t");
            }
            return new BaseResponse(SystemStatusEnum.FAIL.getCode(), stringBuilder.toString() + "：以上用户身份有误！");

        }

        // 防止传入的用户有重复的用户名
        for (ModelEntity modelEntity : request) {
            List<ModelEntity> entityList = request.stream().filter(e -> e.getUsername().equals(modelEntity.getUsername())).collect(Collectors.toList());

            if (entityList.size() > 1) {
                String username = entityList.get(0).getUsername();
                return new BaseResponse(SystemStatusEnum.FAIL.getCode(), username + "：表格中存在重复的用户名，请给别名区分！");
            }
        }
        // 防止传入的用户有重复的学号
        for (ModelEntity modelEntity : request) {
            if (modelEntity.getType() != 2) {
                continue;
            }
            List<ModelEntity> entityList = request.stream().filter(e -> e.getStudentNumber().equals(modelEntity.getStudentNumber())).collect(Collectors.toList());

            if (entityList.size() > 1) {
                Long studentNumber = entityList.get(0).getStudentNumber();
                return new BaseResponse(SystemStatusEnum.FAIL.getCode(), studentNumber + "：表格中存在重复的用户名，请确认导入文件无误！");
            }
        }

        ArrayList<UserEntity> userEntities1 = new ArrayList<>();
        UserEntity userEntity;

        for (ModelEntity entity : request) {
            userEntity = new UserEntity();
            BeanUtils.copyProperties(entity, userEntity);
            String password = entity.getPassword();
            String encode = MD5Util.encode(password);
            userEntity.setPassword(encode);
            userEntity.setHead("http://fangyi-gsy.oss-cn-hangzhou.aliyuncs.com/avatar/0a7d1d3e-3c52-45d0-a8ac-18d74afd1ec4.jpg");
            userEntities1.add(userEntity);
        }
        userService.addBatch(userEntities1);
        return new BaseResponse(SystemStatusEnum.SUCCESS);
    }

    /**
     * 根据用户类型与查询字段模糊查询 (数据与总数量返回)
     *
     * @return
     */
    @ApiOperation(value = "根据用户类型与查询字段模糊查询 (数据与总数量返回)", notes = "根据用户类型与查询字段模糊查询 (数据与总数量返回)")
    @GetMapping("admin/getUsersByTypeAndChar")
    @ParameterValid(apiName = "根据用户类型与查询字段模糊查询 (数据与总数量返回)", formatObj = GetUsersByTypeAndCharRequest.class)
    @TokenValid
    public BaseResponse getUsersByTypeAndChar(GetUsersByTypeAndCharRequest request) {


        Page<UserEntity> page = userService.page(new Page<>(request.getCurrPage(), request.getPageNum()),
                Wrappers.lambdaQuery(new UserEntity()).eq(UserEntity::getType, request.getType())
                        .eq(request.getType() == 2 && request.getId() != null,UserEntity::getStudentNumber, request.getId())
                        .eq(request.getType() == 3 && request.getId() != null,UserEntity::getId, request.getId())
                        .like(StringUtils.isNotBlank(request.getClasses()), UserEntity::getClasses, request.getClasses())
                        .like(StringUtils.isNotBlank(request.getUsername()), UserEntity::getName, request.getUsername())
                        .like(StringUtils.isNotBlank(request.getAddress()), UserEntity::getAddress, request.getAddress())
        );

        List<UserEntity> entities = page.getRecords();

        if (CollectionUtil.isNotEmpty(entities)) {
            BaseResponse success = new BaseResponse(SystemStatusEnum.SUCCESS);
            success.setData(entities);
            success.setTotal(page.getTotal());
            return success;
        } else {
            return new BaseResponse(SystemStatusEnum.SUCCESS.getCode(), "获取数据为空！");
        }
    }

    /**
     * 获取已经填报的信息
     *
     * @return
     */
    @ApiOperation(value = "获取已经填报的信息", notes = "获取已经填报的信息")
    @GetMapping("user/getWriteReport")
    @ParameterValid(apiName = "获取已经填报的信息", formatObj = GetUsersByTypeAndCharRequest.class)
    @TokenValid
    public BaseResponse getWriteReport(GetUsersByTypeAndCharRequest request) {


        Page<UserEntity> page = userService.page(new Page<>(request.getCurrPage(), request.getPageNum()),
                Wrappers.lambdaQuery(new UserEntity()).eq(UserEntity::getType, request.getType())
                        .eq(UserEntity::getStudentNumber, request.getId())
                        .like(StringUtils.isNotBlank(request.getClasses()), UserEntity::getClasses, request.getClasses())
                        .like(StringUtils.isNotBlank(request.getUsername()), UserEntity::getUsername, request.getUsername())
                        .like(StringUtils.isNotBlank(request.getAddress()), UserEntity::getAddress, request.getAddress())
        );

        List<UserEntity> entities = page.getRecords();

        if (CollectionUtil.isNotEmpty(entities)) {
            BaseResponse success = new BaseResponse(SystemStatusEnum.SUCCESS);
            success.setData(entities);
            success.setTotal(page.getTotal());
            return success;
        } else {
            return new BaseResponse(SystemStatusEnum.SUCCESS.getCode(), "获取数据为空！");
        }
    }

    /**
     * 获取相关人数信息
     *
     * @return
     */
    @ApiOperation(value = "获取相关人数信息", notes = "获取相关人数信息")
    @GetMapping("user/getNumberCount")
    @ParameterValid(apiName = "获取已经填报的信息", formatObj = GetUsersByTypeAndCharRequest.class)
    @TokenValid
    public BaseResponse getNumberCount(GetUsersByTypeAndCharRequest request) {

        // 获取已填报人数
        Integer ytbrs = healthService.count(Wrappers.lambdaQuery(new HealthEntity()).like(HealthEntity::getCreatetime,
                DateUtil.getStringDateShort()));
        // 今日高危人数
        Integer gwrs = healthService.count(Wrappers.lambdaQuery(new HealthEntity()).like(HealthEntity::getCreatetime,
                DateUtil.getStringDateShort())
                .eq(HealthEntity::getGohigharea, "是")
                .or()
                .eq(HealthEntity::getHesuanDetail, "阳性")
                .or()
                .isNotNull(HealthEntity::getGeliAdd));

        // 今日经过高危地区人数
        Integer jggwdqrs = healthService.count(Wrappers.lambdaQuery(new HealthEntity()).like(HealthEntity::getCreatetime,
                DateUtil.getStringDateShort())
                .eq(HealthEntity::getGohigharea, "是"));
        LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
        map.put("ytbrs", ytbrs);
        map.put("gwrs", gwrs);
        map.put("jggwdqrs", jggwdqrs);
        BaseResponse success = new BaseResponse(SystemStatusEnum.SUCCESS);
        success.setData(map);
        return success;
    }
}
